package com.bruce.tool.web.filter.util;

import com.bruce.tool.common.util.string.JsonUtils;
import com.bruce.tool.web.filter.core.JsonRequestWrapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 功能 :
 * @author : Bruce(刘正航) 11:48 下午 2020/1/8
 */
public final class RequestUtils {

    /**获取token**/
    public static String fetchToken(HttpServletRequest request) {
        String url = request.getRequestURI();
        String queryString = request.getQueryString();
        if(isGet(request)){
            return DigestUtils.md5Hex(url + queryString);
        }

        if(isForm(request)){
            String params = sortParams(request.getParameterMap(),true);
            return DigestUtils.md5Hex(url + queryString + params);
        }

        if(isJson(request)){
            JsonRequestWrapper myRequestWrapper = null;
            if(request instanceof JsonRequestWrapper){
                myRequestWrapper = (JsonRequestWrapper) request;
            } else if(((ServletRequestWrapper)request).getRequest() instanceof JsonRequestWrapper){
                myRequestWrapper = (JsonRequestWrapper) ((ServletRequestWrapper)request).getRequest();
            }
            if(Objects.isNull(myRequestWrapper)){ return null; }
            String body = myRequestWrapper.getBody();
            String token;
            if (body == null || body.trim().length() == 0) {
                String params = sortParams(request.getParameterMap(),true);
                token = DigestUtils.md5Hex(url + queryString + params);
            } else {
                token = DigestUtils.md5Hex(url + queryString + body);
            }
            return token;
        }
        return null;
    }

    public static boolean isGet(HttpServletRequest request) {
        String method = request.getMethod().toLowerCase();
        if (RequestMethod.GET.name().toLowerCase().equals(method)) {
            return true;
        }
        return false;
    }

    public static  boolean isForm(HttpServletRequest request){
        if (request.getContentType() != null
                && request.getContentType().contains(MediaType.MULTIPART_FORM_DATA_VALUE)) {
            return true;
        }
        return false;
    }

    public static boolean isJson(HttpServletRequest request){
        if (request.getContentType() != null
                && request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
            return true;
        }
        return false;
    }

    /**拼接参数**/
    private static String sortParams(Map<String, String[]> params,boolean encode) {
        StringBuilder sb = new StringBuilder(1024);
        // factory signature:
        SortedMap<String, String[]> map = Collections.synchronizedSortedMap(new TreeMap<>(params));
        return loopParams(encode, sb, map.entrySet());
    }

    /**循环map参数**/
    private static String loopParams(boolean encode, StringBuilder sb, Set<Map.Entry<String, String[]>> entries) {
        for (Map.Entry<String, String[]> entry : entries) {
            if (Objects.nonNull(entry.getValue())) {
                String key = entry.getKey();
                String value = JsonUtils.objToStr(entry.getValue());
                if (encode) {
                    value = urlEncode(value);
                }
                sb.append(key).append('=').append(value).append('&');
            }
        }
        // remove last '&':
        if (StringUtils.isNotBlank(sb)) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    private static String urlEncode(String encode) {
        try {
            return URLEncoder.encode(encode, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("UTF-8 encoding not supported!");
        }
    }
}
